// 线程
#include <iostream>

#include <pthread.h>

using namespace std;

#define THREAD_COUNT 5

typedef struct thread_data{
   int  thread_id;
   char *message;
} thread_data;

// 线程的运行函数
void *say_hello(void *args) {
  cout << "HELLO" << endl;
  return 0;
}

void *print(void *td) {
  // 对传入的参数进行强制类型转换，由无类型指针变为整形数指针，然后再读取;
  thread_data *d; // 无类型转为 thread_data 指针类型
  d = (thread_data *)td;

  // cout << "Hello Runoob! struct, " << d << endl;
  cout << "Hello Runoob! 线程 ID, " << d->thread_id << endl;
  cout << "Hello Runoob! 线程 message, " << d->message << endl;

  pthread_exit(NULL);
}

void run_thread() {
  // 定义线程的 id 变量，多个变量使用数组

  pthread_t tids [THREAD_COUNT];

  for (int i = 0; i< THREAD_COUNT; i++) {

    //参数依次是：创建的线程id，线程参数，调用的函数，传入的函数参数
    int ret = pthread_create(&tids[i], NULL, say_hello, NULL);

    if (ret != 0)
    {
      cout << "线程创建失败，线程 id 为：" << tids[i] << endl;
    }
  };
};

int run_thread_params(pthread_t *threads, struct thread_data *td)
{
  int rc;
  int i;
  for (i = 0; i < THREAD_COUNT; i++)
  {
    // indexes[i] = i; //先保存i的值
    // string str = "This is message" + to_string(i);
    cout << "main() : 创建线程, " << i << endl;
    td[i].thread_id = i;
    td[i].message = (char *)"This is message";
    // NOTE: 传入的时候必须强制转换为void* 类型，即无类型指针
    rc = pthread_create(&threads[i], NULL,
                        print, (void *)&(td[i])); // 这里指针类型强行转换为 void 类型

    cout << "main 创建线程结果 " << rc << endl;
    if (rc)
    {
      cout << "Error:无法创建线程," << rc << endl;
      exit(-1);
    }
  }
  return 0;
}

int main(int argc, char **argv)
{
  pthread_t threads[THREAD_COUNT];
  // int indexes[THREAD_COUNT]; // 用数组来保存 i 的值
  thread_data td[THREAD_COUNT];

  // run_thread();
  // NOTE: 如果将创建线程的逻辑 封装在函数中，
  // 有可能函数运行结束之后，线程还在运行，那么如果线程中使用了函数中的局部变量，
  // 可能会导致线程无法访问到改变量，因为函数运行结束之后，会出栈，那么函数内部的变量会销毁
  run_thread_params(threads, td);
  //主线程 等各个线程退出后，进程才结束，否则进程强制结束了，线程可能还没反应过来；
  // cout << "wait" << endl;
  pthread_exit(NULL);

  // cout << "quit" << endl;

  return 0;
}

// NOTE: 编译需要使用 pthread 库来进行编译
// g++ -I ./ ./src/advanced/thread.cpp -lpthread --std=c++11 -o ./bin/thread

// 生成 core 文件； 使用 gdb 来调试文件 gdb ./src/adv../thread.cpp core